import { GoodsSkuType } from "@/constants/enums/goods"
import Goods from "@/services/goods/typings"
import { CloseCircleFilled, DeleteOutlined, HolderOutlined, PlusCircleFilled, PlusOutlined } from "@ant-design/icons"
import { Input, Button, Tag, Modal, message, Checkbox, Image, Tooltip } from "antd"
import dayjs from "dayjs"
import { useState } from "react"
import { Access } from '@umijs/max'
import {
  DndContext,
  closestCenter,
  KeyboardSensor,
  PointerSensor,
  useSensor,
  useSensors,
} from "@dnd-kit/core";
import {
  arrayMove,
  SortableContext,
  sortableKeyboardCoordinates,
  rectSortingStrategy,
  useSortable,
} from "@dnd-kit/sortable";
import { CSS } from "@dnd-kit/utilities"
import { fileUp } from "@/services/common"
import { useModel } from "@umijs/max"

const TagItem: React.FC<{value: Goods.SkuValue, addPic: boolean, del: () => void, onImgChange: (val?: string) => void}> = props => {
  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging
  } = useSortable({ id: props.value.id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    zIndex: isDragging ? "100" : "auto",
    opacity: isDragging ? 0.3 : 1
  }

  const removeImg = () => {
    props.onImgChange('')
  }
  const onChange = (e: any) => {
    const _loading = message.loading('上传中', 0)
    const { files } = e.target
    const _promiseList = []
    for (const file of files) {
      const _formData = new FormData()
      _formData.append('type', '2')
      _formData.append('file', file)
      _promiseList.push(fileUp(_formData))
    }
    Promise.all(_promiseList).then(res => {
      props.onImgChange(res[0].data)
    }).finally(() => {
      _loading()
    })
  }

  return <div className="shrink-0" ref={setNodeRef} style={style}>
    <Tag closable style={{margin: 0}} onClose={props.del}>
      <span {...listeners} {...attributes}>{ props.value.valueName }</span>
    </Tag>
    <Access accessible={props.addPic}>
      <div className="relative mt-1">
        <Access accessible={!props.value.valueDesc} fallback={
          <div className="w-20 h-20 rounded-xl border-dashed border flex items-center justify-center relative">
            <Image style={{width: 80, height: 80, borderRadius: 10, objectFit: 'cover'}} src={props.value.valueDesc} />
            <Tooltip title='删除图片'>
              <CloseCircleFilled style={{position: 'absolute', top: 4, right: 4}} onClick={() => removeImg()} />
            </Tooltip>
          </div>
        }>
          <div className="w-20 h-20 rounded-xl border-dashed border flex items-center justify-center relative">
            <PlusOutlined className='text-2xl' />
            <input className="absolute inset-0 opacity-0 cursor-pointer" type="file" accept='image/jpg, image/png' onChange={onChange} />
          </div>
          <div style={{color: '#ff4040'}}>请添加规格图片</div>
        </Access>
      </div>
    </Access>
  </div>
}

const Item: React.FC<{value: Goods.Sku, index: number, onDel: () => void, onChange: () => void}> = props => {
  const [value, setValue] = useState<Goods.Sku>(props.value)

  const onNameChange = (val: string) => {
    setValue({...value, className: val})
    props.value.className = val
  }
  const onImgAbleChange = (val: boolean) => {
    setValue({...value, _img: val})
    props.value._img = val
  }
  const delValue = (index: number) => {
    const newValue = {...value, values: value.values.filter((_, idx) => idx !== index)}
    setValue(newValue)
    props.value.values = newValue.values
    props.onChange()
  }
  const onImgChange = (index: number, src?: string) => {
    const newValue = {...value, values: value.values.map((item, idx) => {
      if (idx !== index) return item
      return {...item, valueDesc: src}
    })}
    setValue(newValue)
    props.value.values = newValue.values
  }
  const addValue = () => {
    let valueName = ''
    Modal.confirm({
      icon: <PlusCircleFilled />,
      title: '添加选项',
      content: <Input placeholder="选项名称" onChange={({target}) => valueName = target.value} maxLength={20} />,
      onOk: async () => {
        valueName = valueName.trim()
        if (!valueName) {
          message.error('请输入有效的选项名称')
          return Promise.reject()
        }
        if (value.values.some(it => it.valueName === valueName)) {
          message.error('已存在该选项，不可重复添加')
          return Promise.reject()
        }
        const _fakeId = String(dayjs().valueOf())
        const newValue = {...value, values: value.values.concat({id: _fakeId, fakeId: _fakeId, valueName})}
        setValue(newValue)
        props.value.values = newValue.values
        props.onChange()
        return Promise.resolve()
      }
    })
  }

  const {
    attributes,
    listeners,
    setNodeRef,
    transform,
    transition,
    isDragging
  } = useSortable({ id: props.value.id })

  const style = {
    transform: CSS.Transform.toString(transform),
    transition,
    zIndex: isDragging ? "100" : "auto",
    opacity: isDragging ? 0.3 : 1
  }

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates
    })
  );

  const handleDragEnd = (event: any) => {
    const { active, over } = event;

    if (active.id !== over.id) {
      const oldIndex = value.values.findIndex(it => it.id === active.id);
      const newIndex = value.values.findIndex(it => it.id === over.id);

      const newValue = {...value, values: arrayMove(value.values, oldIndex, newIndex)}
      setValue(newValue)
      props.value.values = newValue.values
    }
  };

  return <div
    className="flex gap-2 rounded-lg p-3" ref={setNodeRef}
    style={{...style, background: '#f8f8f8'}}
  >
    <div className="shrink flex items-center cursor-move p-x-1" {...listeners} {...attributes}>
      <HolderOutlined />
    </div>
    <div className="grow">
      <div className="flex items-center gap-2">
        <div className="lh-8">规格名：</div>
        <Input value={value.className} onChange={({target}) => onNameChange(target.value)} style={{width: 240}} />
        <Access accessible={props.index < 1}>
          <Checkbox checked={value._img} onChange={({target}) => onImgAbleChange(target.checked)}>添加规格图片</Checkbox>
        </Access>
      </div>
      <div className="flex mt-2 gap-2">
        <div className="lh-8">规格值：</div>
        <DndContext
          sensors={sensors}
          collisionDetection={closestCenter}
          onDragEnd={handleDragEnd}
        >
          <div className="grow flex flex-wrap gap-2">
            <SortableContext items={props.value.values} strategy={rectSortingStrategy}>
              {
                props.value.values.map((val, valIndex) => <TagItem 
                  key={val.valueId || val.fakeId}
                  addPic={!!value._img}
                  value={val}
                  del={() => delValue(valIndex)} 
                  onImgChange={val => onImgChange(valIndex, val)}
                />)
              }
            </SortableContext>
            <Tag onClick={() => addValue()} className="cursor-pointer" style={{margin: 0, height: 'fit-content'}}>添加规格值</Tag>
          </div>
        </DndContext>
      </div>
    </div>
    <div className="shrink flex items-center cursor-pointer" onClick={() => props.onDel()}>
      <DeleteOutlined style={{color: '#ff4040'}} />
    </div>
  </div>
}

const GoodsSkuInfo: React.FC = () => {
  const { skuList, setSkuList, generateGoodsStock } = useModel('mall.physical.goods.goods')
  
  const onDel = (index: number) => {
    console.log('onDel')
    generateGoodsStock(skuList.filter((_, idx) => idx !== index))
  }
  const add = () => {
    console.log('onAdd')
    const _fakeId = String(dayjs().valueOf())
    generateGoodsStock(skuList.concat([{
      id: _fakeId,
      fakeId: _fakeId,
      className: '',
      classType: GoodsSkuType.商品,
      values: [],
    }]))
  }

  const onChange = () => {
    console.log('onChange')
    generateGoodsStock([...skuList])
  }

  const sensors = useSensors(
    useSensor(PointerSensor),
    useSensor(KeyboardSensor, {
      coordinateGetter: sortableKeyboardCoordinates
    })
  );

  const handleDragEnd = (event: any) => {
    const { active, over } = event;

    if (active.id !== over.id) {
      const oldIndex = skuList!.findIndex(it => it.id === active.id);
      const newIndex = skuList!.findIndex(it => it.id === over.id);

      setSkuList(arrayMove(skuList!, oldIndex, newIndex));
    }
  };

  return (
    <DndContext
      sensors={sensors}
      collisionDetection={closestCenter}
      onDragEnd={handleDragEnd}
    >
      <div className="flex flex-col gap-4">
        <SortableContext items={skuList} strategy={rectSortingStrategy}>
          {
            skuList.map((sku, skuIndex) => {
              return <Item key={sku.classId || sku.fakeId} value={sku} index={skuIndex} onDel={() => onDel(skuIndex)} onChange={onChange} />
            })
          }
        </SortableContext>
        <div className="h-15 flex items-center">
          <Button onClick={add}>添加规格</Button>
        </div>
      </div>
    </DndContext>
  )
}

export default GoodsSkuInfo
